import type { RadioChangeEvent } from 'antd';
import { Button, Col, Form, Input, message, Radio, Row, Select, Steps } from 'antd';
import { useEffect, useState } from 'react';
import { v4 as uuidv4 } from 'uuid';

import { get, post } from '@/api';
import { CodeMirrorJSON, CodeMirrorJSONRef } from '@/components/business/CodeMirrorJSON';
import { useDictStore } from '@/store/dict';

import { ApiModelScript } from '../ApiModelScript';
import { DataPreview } from '../DataPreview';
import { ApiModelDataStructure, ApiModelDataStructureRef } from '../DataStructure';
import { VariablesAdd, VariablesAddRef } from '../ParametersAdd';
import { INPUT_MAX_DATA_MODEL_NAME, INPUT_MAX_DESC, INPUT_MAX_HTTPURL, RuleForm, SerializeType } from './data';
interface ApiModelAddProps extends HTMLElementProps {
    onInit: () => void;
    onActiveStep: (step: number) => void;
    onExecute: (execute: boolean) => void;
    onClosed: (refresh: boolean) => void;
    onTableRequest: (refresh: boolean) => void;
}

export interface ApiModelAddRef {
    initData: (rowData?: any) => void;
    last: () => void;
    save: () => void;
    handleConfirm: () => void;
}

type ToRawFunction = <T>(obj: T) => T;

export const ApiModelAdd = memo(
    forwardRef<ApiModelAddRef, ApiModelAddProps>((props, ref) => {
        const dictStore = useDictStore();

        const [messageApi, contextHolder] = message.useMessage();
        const [activeStep, setActiveStep] = useState<number>(0);
        const [executeDone, setExecuteDone] = useState<boolean>(false);
        const [apiModelID, setApiModelID] = useState<number>();

        // 第一步，条件设置
        const ruleFormRef = useRef<any>(null);
        const [form] = Form.useForm();
        const [implicitFormData, setImplicitFormData] = useState<RuleForm>({
            varMode: undefined,
            modelTemplate: undefined,
            paramsJson: undefined,
            httpMethod: 'POST',
            serializeScript: undefined,
            serializeType: SerializeType.JSON,
        });
        const parametersAddRef = useRef<VariablesAddRef>(null);
        const codeRef = useRef<any>(null);
        const [templateOptions, setTemplateOptions] = useState<any>([]);

        // JSON编辑器
        const jsonEditorRef = useRef<CodeMirrorJSONRef>(null);
        const [jsonCode, setJsonCode] = useState<string>('');
        const [executeLoading, setExecuteLoading] = useState<boolean>(false);
        const toRaw: ToRawFunction = obj => obj;

        // 预览数据
        const apiModelDataStructureRefs = useRef<ApiModelDataStructureRef>(null);
        const [tesResTableData, setTesResTableData] = useState<any>([]);
        const [tesResTableColumn, setTesResTableColumn] = useState<any>([]);

        const initDataSource = async (rowData?: any) => {
            setActiveStep(0);
            setApiModelID(Number(rowData?.id));
            props.onActiveStep(0);
            setTemplateOptions(dictStore.dictApiTemplateOptions || []);

            // 回显
            if (rowData?.id) {
                get('/api/get', { id: rowData.id } as never).then((res) => {
                    ruleFormRef.current?.setFieldsValue({
                        modelName: res.apiName,
                        modelDesc: res.apiDesc,
                        httpUrl: res.httpUrl,
                        modelTemplate: res.template,
                        varMode: res.varMode
                    });
                    setImplicitFormData({
                        varMode: res.varMode,
                        modelTemplate: res.template,
                        paramsJson: res.paramsJson,
                        httpMethod: res.httpMethod,
                        serializeScript: res.serializeScript,
                        serializeType: res.serializeType ? SerializeType[res.serializeType] : SerializeType.JSON,
                    });
                    res.varMode === 0 && parametersAddRef.current?.initData(res.reqVariables);
                });
            } else {

            }
        };

        // 构建预览数据
        const buildDataPreview = (data: any) => {
            const newData = data ? data.map((item: any) => {
                return {
                    id: uuidv4(),
                    ...item
                };
            }) : [];
            setTesResTableData(newData);
            setTesResTableColumn([]);
            if (data && data.length) {
                const keys = Object.keys(data[0]);
                const newColumn = keys.map((item: string) => {
                    return {
                        title: item,
                        dataIndex: item,
                        key: item
                    };
                });
                setTesResTableColumn(newColumn);
            }
        };

        // 数据结构变化回调
        const dataStructureChange = (newList: any) => {
            const newData = newList || [{ checked: false, varLabel: '', varName: '' }];
            const columns: { title: string; dataIndex: string; key: string }[] = [];
            if (Array.isArray(newData) && newData.length > 0) {
                for (const iterator of newData) {
                    if (iterator && iterator.checked) {
                        const column = {
                            title: iterator.varLabel,
                            dataIndex: iterator.varName,
                            key: iterator.varName
                        };
                        columns.push(column);
                    }
                }
            }
            setTesResTableColumn(columns);

        };

        // 上一步
        const isLast = () => {
            if (activeStep > 0) {
                const lastStep = activeStep - 1;
                setActiveStep(lastStep);
                props.onActiveStep(lastStep);
            }
        };

        // 初始化下一步数据
        const initNext = () => {
            if (activeStep < 1) {
                const nextStep = activeStep + 1;
                setActiveStep(nextStep);
                props.onActiveStep(nextStep);
            }
            setExecuteDone(false);
            props.onExecute(false);

            // 回显数据
            const formData = implicitFormData;
            const jsonObj = toRaw(formData).paramsJson;
            setJsonCode(jsonObj);
        };

        const isSave = () => {
            if (activeStep === 0) {
                formValidate();
            }
        };

        // 打开编辑脚本窗口
        const editScript = () => {
            const { serializeScript } = implicitFormData;
            codeRef && codeRef.current.initData(serializeScript);
        };

        // 获取编辑确认的脚本内容
        const handleTemplateValue = (val: any) => {
            setImplicitFormData({
                ...implicitFormData,
                serializeScript: val
            });
        };

        // 使用的解析模板变化回调
        const modelTemplateChange = (val: string) => {
            ruleFormRef.current?.setFieldsValue({
                modelTemplate: val
            });
            serializeScriptRequest(val);
        };

        // 模板
        const serializeScriptRequest = (val: string) => {
            const { modelTemplate } = ruleFormRef.current?.getFieldsValue();
            if (!modelTemplate) {
                setImplicitFormData({
                    ...implicitFormData,
                    modelTemplate: '',
                    serializeScript: ''
                });
                return;
            }
            const params: any = {
                name: modelTemplate
            };
            get('/api/template', params as never).then((res) => {
                setImplicitFormData({
                    ...implicitFormData,
                    modelTemplate: val,
                    serializeScript: res
                });
            });
        };

        // 新增请求
        const addRequest = () => {
            console.log('新增请求');
            const { modelName, modelDesc, httpUrl, modelTemplate } = ruleFormRef.current?.getFieldsValue();
            const { varMode, httpMethod, serializeType, serializeScript } = implicitFormData;
            let variableDada: never[] = [];
            if (varMode === 0) {
                variableDada = parametersAddRef.current?.getData() || [];
            }
            const params: any = {
                apiName: modelName,
                apiDesc: modelDesc,
                httpUrl,
                httpMethod,
                serializeType,
                serializeScript: serializeScript ? serializeScript : '',
                template: modelTemplate ? modelTemplate : '',
                varMode: varMode,
                reqVariables: variableDada,
            };
            post('/api/add', {
                data: params
            }).then((res) => {
                if (res) {
                    // 新增成功
                    setApiModelID(res);
                    props.onTableRequest(true);
                    initNext();
                }
            });
        };

        // 修改请求
        const modifyRequest = () => {
            console.log('修改请求');
            const { modelName, modelDesc, httpUrl, modelTemplate } = ruleFormRef.current?.getFieldsValue();
            const { varMode, httpMethod, serializeType, serializeScript } = implicitFormData;
            let variableDada: never[] = [];
            if (varMode === 0) {
                variableDada = parametersAddRef.current?.getData() || [];
            }
            const params: any = {
                apiName: modelName,
                apiDesc: modelDesc,
                httpUrl,
                httpMethod,
                serializeType,
                serializeScript: serializeScript ? serializeScript : '',
                template: modelTemplate ? modelTemplate : '',
                varMode: varMode,
                reqVariables: variableDada,
            };
            post('/api/update', {
                params: { id: apiModelID },
                data: params
            }).then((res) => {
                props.onTableRequest(true);
                initNext();
            });
        };

        const formValidate = async () => {
            if (!form) return;
            form.validateFields().then((values) => {
                // form.resetFields();
                if (values) {
                    if (apiModelID) {
                        modifyRequest();
                    } else {
                        addRequest();
                    }
                }
            }).catch(() => { });
        };

        // 执行
        const exeRequest = async () => {
            console.log('执行');
            let json = jsonEditorRef.current?.getData() || '';
            json && json.trim();
            if (json && typeof json === 'string') {
                json = json.trim();
                try {
                    if (json) json = JSON.parse(json);
                } catch (error) {
                    console.error(error);
                    messageApi.warning('JSON数据格式不正确，请修改后重试');
                    return;
                }
            }

            setExecuteLoading(true);
            const params: any = {
                apiId: apiModelID,
                param: json || {}
            };
            try {
                post('/api/execute', {
                    data: params
                }).then((res) => {
                    if (res) {
                        setExecuteDone(true);
                        props.onExecute(true);
                        setExecuteLoading(false);
                        // 数据结构
                        if (res && Array.isArray(res) && res.length) {
                            apiModelDataStructureRefs && apiModelDataStructureRefs.current?.initData(res[0]);
                        } else {
                            apiModelDataStructureRefs && apiModelDataStructureRefs.current?.initData([]);
                        }
                        // 数据预览
                        buildDataPreview(res);
                    } else {
                        setExecuteDone(false);
                        setExecuteLoading(false);
                    }
                });
            } catch (e) {
                setExecuteDone(false);
                setExecuteLoading(false);
            }
        };

        const isHandleConfirm = () => {
            let respVariables: never[] = [];
            respVariables = apiModelDataStructureRefs.current?.getData() || [];
            post('/api/setRespVariables', {
                params: { id: apiModelID },
                data: respVariables
            }).then((res) => {
                props.onClosed(true);
            });
        };

        useEffect(() => {
            props.onInit();
        }, []);

        useImperativeHandle(ref, () => ({
            initData: (rowData: any) => {
                initDataSource(rowData);
            },
            last: () => {
                isLast();
            },
            save: () => {
                isSave();
            },
            handleConfirm: () => {
                isHandleConfirm();
            },
        }));

        return (
            <div className='w-full h-full'>
                <div className="flex justify-center">
                    <div className="w-1/2">
                        <Steps current={activeStep} labelPlacement="vertical" items={[
                            {
                                title: '连接API'
                            },
                            {
                                title: '提取数据'
                            },
                        ]}>
                        </Steps>
                    </div>
                </div>
                <div style={{ height: '50vh', overflowY: 'auto' }}>
                    {
                        <div style={{ width: 'calc(100% - 16px)', display: activeStep === 0 ? 'block' : 'none' }}>
                            <Form
                                ref={ruleFormRef}
                                form={form}
                                layout="vertical"
                            >
                                {/* 接口名称 */}
                                <Row>
                                    <Col span={24}>
                                        <Form.Item label="模型名称" name="modelName" rules={[{ required: true, message: '请填写模型名称' }]}>
                                            <Input type="text" placeholder="请输入" max={INPUT_MAX_DATA_MODEL_NAME} />
                                        </Form.Item>
                                    </Col>
                                </Row>
                                {/* API说明 */}
                                <Row>
                                    <Col span={24}>
                                        <Form.Item label="模型描述" name="modelDesc" rules={[{ required: true, message: '请填写模型描述' }]}>
                                            <Input.TextArea rows={4} placeholder="请输入" maxLength={INPUT_MAX_DESC} />
                                        </Form.Item>
                                    </Col>
                                </Row>
                                {/* URL */}
                                <Row>
                                    <Col span={24}>
                                        <Form.Item label="模型调用地址" name="httpUrl" rules={[{ required: true, message: '请填写模型调用地址' }]}>
                                            <Input placeholder="请输入" addonBefore={(
                                                <Select
                                                    value={implicitFormData.httpMethod}
                                                    onChange={(val) => setImplicitFormData({
                                                    ...implicitFormData,
                                                    httpMethod: val
                                                })}>
                                                    <Select.Option value="POST">POST</Select.Option>
                                                    <Select.Option value="GET">GET</Select.Option>
                                                </Select>
                                            )} max={INPUT_MAX_HTTPURL} />
                                        </Form.Item>
                                    </Col>
                                </Row>

                                <Form.Item label="选择解析工具" name="modelTemplate">
                                    <div className="flex justify-end w-full">
                                        <div className="grow pr-8">
                                            <Select value={implicitFormData.modelTemplate} placeholder="请选择" allowClear className="w-full" onChange={modelTemplateChange}>
                                                {
                                                    templateOptions.map((item: any) => {
                                                        return (
                                                            <Select.Option value={item.value} key={item.value} disabled={item.disabled}>{item.label}</Select.Option>
                                                        );
                                                    })
                                                }

                                            </Select>
                                        </div>
                                        <Button type="primary" onClick={editScript}> 编辑脚本 </Button>
                                    </div>
                                </Form.Item>
                                <Form.Item label="变量类型" name="varMode" rules={[{ required: true, message: '请选择变量类型' }]}>
                                    <div className="w-full">
                                        <div>
                                            <Radio.Group
                                                value={implicitFormData.varMode}
                                                onChange={(e: RadioChangeEvent) => setImplicitFormData({
                                                    ...implicitFormData,
                                                    varMode: e.target.value
                                                })}
                                            >
                                                <Radio value={0}>自定义入参</Radio>
                                                <Radio value={1}>依赖前置节点</Radio>
                                            </Radio.Group>
                                        </div>
                                        <div className="w-full" style={{ display: implicitFormData.varMode === 0 ? 'block' : 'none' }}>
                                            <VariablesAdd ref={parametersAddRef} />
                                        </div>
                                    </div>
                                </Form.Item>
                            </Form>
                            <ApiModelScript ref={codeRef} onValue={handleTemplateValue} />
                        </div >
                    }
                    {
                        <div style={{ width: 'calc(100% - 16px)', display: activeStep === 1 ? 'block' : 'none' }}>
                            <p>请求参数</p>
                            <CodeMirrorJSON ref={jsonEditorRef} code={jsonCode} />
                            <div className="py-16 flex justify-end">
                                <Button loading={executeLoading} onClick={exeRequest}>执行</Button>
                            </div>
                            {
                                <div style={{ display: executeDone ? 'block' : 'none' }}>
                                    <ApiModelDataStructure ref={apiModelDataStructureRefs} onDataChange={(newList: any) => dataStructureChange(newList)} />
                                    <div className="py-16">
                                        <DataPreview dataSource={tesResTableData} columns={tesResTableColumn} />
                                    </div>
                                </div>
                            }
                        </div>
                    }
                </div >
            </div >
        );
    })
);
